package Herramientas;

import AG.Arbol;

public class Funciones {

	/**
	 * 
	 * @param nombreFuncion
	 *            raiz de la funcion
	 * @param arbol
	 *            arbol con raiz en Funcion
	 * @param confActual
	 *            configuracionActual para ejecutar la funcion
	 * @return
	 */

	public static Resultado ejecutaFuncion(String nombreFuncion, Arbol arbol,
			Configuracion confActual) {
		Arbol arg0 = null, arg1 = null;
		if (nombreFuncion.equals("EQ")) {
			arg0 = arbol.getHijos()[0];
			arg1 = arbol.getHijos()[1];
			return Funciones.ejecutaFuncionEQ(arg0, arg1, confActual);
		}
		if (nombreFuncion.equals("MM")) {
			arg0 = arbol.getHijos()[0];
			return Funciones.ejecutaFuncionMM(arg0, confActual);
		}
		if (nombreFuncion.equals("MP")) {
			arg0 = arbol.getHijos()[0];
			return Funciones.ejecutaFuncionMP(arg0, confActual);
		}
		if (nombreFuncion.equals("DU")) {
			arg0 = arbol.getHijos()[0];
			arg1 = arbol.getHijos()[1];
			return Funciones.ejecutaFuncionDU(arg0, arg0, confActual);
		}
		if (nombreFuncion.equals("NOT")) {
			arg0 = arbol.getHijos()[0];
			return Funciones.ejecutaFuncionNOT(arg0, confActual);
		}

		// ES UN TERMINAL
		return new Resultado(confActual, true);

	}

	private static Resultado ejecutaFuncionNOT(Arbol arg0,
			Configuracion confActual) {

		boolean re = false;
		if (arg0.getValor().equals("BS") || arg0.getValor().equals("CP")
				|| arg0.getValor().equals("SN")) {
			String value = confActual.dameValor(arg0.getValor());
			if (value == null)
				return new Resultado(confActual, true);
		return new Resultado(confActual, true);
		}
		Resultado r = Funciones.ejecutaFuncion(arg0.getValor(), arg0,
				confActual);
		return new Resultado(r.getConf(), !r.isResultado());

	}

	private static Resultado ejecutaFuncionDU(Arbol arg0, Arbol arg02,
			Configuracion confActual) {
		int limiteIteraciones = 20;
		int i =0;
		Configuracion c = confActual.copia();
		// Lo ejecuto una primera vez
		Resultado resultadoAccion = Funciones.ejecutaFuncion(arg0.getValor(), arg0, confActual);
		c = resultadoAccion.getConf().copia();
		Resultado resultadoPredicado = Funciones.ejecutaFuncion(arg02.getValor(), arg02, c);
		c = resultadoPredicado.getConf().copia();
		boolean sigue = resultadoPredicado.isResultado();
		// Itero si es falso o null
		while(!sigue && limiteIteraciones>i){
			 resultadoAccion = Funciones.ejecutaFuncion(arg0.getValor(), arg0, c);
			 c = resultadoAccion.getConf().copia();
			 resultadoPredicado = Funciones.ejecutaFuncion(arg02.getValor(), arg02, c);
			 c = resultadoPredicado.getConf().copia();
			 sigue = resultadoPredicado.isResultado();
			 i++;
		}
		if(i>=limiteIteraciones){
			return new Resultado(c,false);
		}
		return new Resultado(c,true);
	}

	private static Resultado ejecutaFuncionMP(Arbol arg0,
			Configuracion confActual) {
		Configuracion nuevaConf = confActual.copia();
		boolean b = nuevaConf.ejecutaMP(arg0.getValor());
		return new Resultado(nuevaConf, b);

	}

	private static Resultado ejecutaFuncionMM(Arbol arg0,
			Configuracion confActual) {
		// Ejecuto la accion
		Configuracion nuevaConf = confActual.copia();
		boolean b = nuevaConf.ejecutaMM(arg0.getValor());
		return new Resultado(nuevaConf, b);
	}

	private static Resultado ejecutaFuncionEQ(Arbol arg0, Arbol arg1,
			Configuracion confActual) {
		Resultado r1 = Funciones.ejecutaFuncion(arg0.getValor(), arg0,
				confActual);
		Resultado r2 = Funciones.ejecutaFuncion(arg1.getValor(), arg1,
				r1.getConf());

		 if(r1.isResultado() == r2.isResultado() ) 
			 return new Resultado(r2.getConf(),true);
		

		return new Resultado(confActual, false);
	}
}
